import hashlib
import importlib
import re
import time
import random
import string

from user_agents import parse


def hump_to_underline(text):
    """
    驼峰转下划线
    :param text:
    :return:
    """
    res = []
    for index, char in enumerate(text):
        if char.isupper() and index != 0:
            res.append("_")
        res.append(char)
    return "".join(res).lower()


def underline_to_hump(text):
    """
    下划线转大驼峰
    :param text:
    :return:
    """
    arr = text.lower().split("_")
    res = []
    for i in arr:
        res.append(i[0].upper() + i[1:])
    return "".join(res)


def underline_to_camel(text):
    """
    下划线转小驼峰
    :param text:
    :return:
    """
    s = underline_to_hump(text)
    return s[0].lower() + s[1:]


def md5_encrypt(string):
    # 创建一个md5 hash对象
    m = hashlib.md5()

    # 必须使用encode()函数对字符串进行编码，否则会抛出TypeError异常
    m.update(string.encode("utf-8"))

    # 使用hexdigest()函数获取加密后的16进制结果
    return m.hexdigest()


def random_string(len):
    """
    生成随机字符串
    """

    return "".join(
        random.choice(string.ascii_letters + string.digits) for _ in range(len)
    )


def load_model(model_name):
    """
    加载模型
    """
    module_path = f"models.{hump_to_underline(model_name)}"
    try:
        model_module = importlib.import_module(module_path)
        return getattr(model_module, underline_to_hump(hump_to_underline(model_name)))
    except (ImportError, AttributeError) as e:
        print(f"Failed to load model {model_name}: {e}")
        return None


def build_tree(nodes_list):
    """
    构建树，parent_id默认为0
    """
    return _build_tree(nodes_list=nodes_list, parent_id="0")


def _build_tree(nodes_list, parent_id):
    """
    递归构建树结构
    """
    if nodes_list is None or len(nodes_list) == 0:
        return []
    children = []
    for node in nodes_list:
        if node.get("parentId") == parent_id:
            children.append(node)
            node["children"] = _build_tree(nodes_list, node.get("id"))
            if len(node["children"]) == 0:
                del node["children"]
    return children


def recursion_tree(tree_data, row_handle_before, row_handle_after, res):
    """
    递归树结构
    """
    if tree_data is None or len(tree_data) == 0:
        return res
    for data in tree_data:
        if row_handle_before is not None:
            row_handle_before(data, res)
        recursion_tree(data.get("children"), row_handle_before, row_handle_after, res)
        if row_handle_after is not None:
            row_handle_after(data, res)


def parse_user_agent(userAgentStr):
    """
    解析userAgent
    """
    # user_agent_string = request.headers.get('User-Agent')
    user_agent = parse(userAgentStr)
    # 提取浏览器和操作系统信息
    browser = user_agent.browser
    os = user_agent.os
    return {"browser": browser.family, "os": f"{os.family} {os.version_string}"}


def get_client_ip(request):
    """
    获取客户端IP
    """
    return request.remote_addr


def ant_matcher(request_path, pattern):
    """
    Ant风格路径匹配
    """
    parts = pattern.split("/")
    matcher = re.compile(
        "^"
        + "/".join(
            [
                re.escape(part).replace("\\*", ".*").replace("\\**", "(/.*)?")
                for part in parts
            ]
        )
        + "$"
    )
    return bool(matcher.match(request_path))


def extract_fields(original_dict, field_names_str):
    """
    从原始字典中提取指定字段名的值，并返回一个新字典。

    :param original_dict: 包含所有数据的原始字典
    :param field_names_str: 字符串，包含以逗号分隔的需要提取的字段名
    :return: 一个新字典，包含提取的字段名及其对应的值
    """
    # 创建一个空字典用于存放提取的字段
    extDict = {}
    if field_names_str is None or field_names_str == "":
        return extDict
    # 分割字符串以获取字段名列表
    field_names = field_names_str.split(",")

    # 遍历字段名列表，从原始字典中提取值
    for field_name in field_names:
        # 如果字段名在原始字典中，则添加到extDict字典中
        if field_name in original_dict:
            extDict[field_name] = original_dict[field_name]

    return extDict


class SnowflakeIDGenerator:
    def __init__(self, worker_id, datacenter_id, epoch=1288834974657):
        self.worker_id = worker_id & 0x0F  # 保证worker_id不超过4位
        self.datacenter_id = datacenter_id & 0x07  # 保证datacenter_id不超过3位
        self.epoch = epoch
        self.sequence = 0
        self.last_timestamp = -1

    def _next_id(self):
        timestamp = int(time.time() * 1000)

        if timestamp < self.last_timestamp:
            raise Exception(
                "Clock moved backwards. Refusing to generate id for %d milliseconds"
                % (self.last_timestamp - timestamp)
            )

        if timestamp == self.last_timestamp:
            self.sequence = (self.sequence + 1) & 0xFFF
            if self.sequence == 0:
                timestamp = self._wait_for_next_millis(self.last_timestamp)
        else:
            self.sequence = 0

        self.last_timestamp = timestamp

        new_id = (
            ((timestamp - self.epoch) << 22)
            | (self.datacenter_id << 17)
            | (self.worker_id << 12)
            | self.sequence
        )
        return new_id

    def _wait_for_next_millis(self, last_timestamp):
        timestamp = last_timestamp
        while timestamp <= last_timestamp:
            timestamp = int(time.time() * 1000)
        return timestamp

    def generate(self):
        return self._next_id()


generator = SnowflakeIDGenerator(worker_id=1, datacenter_id=1)


def generate_id():
    return generator.generate()
